package com.example.blog.controller;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.blog.config.PublisherAware;
import com.example.blog.domain.*;
import com.example.blog.dto.writing.AdminWritingSelectDto;
import com.example.blog.dto.operationalLogs.OperationLogsDto;
import com.example.blog.dto.writing.AdminWritingsUpdateDto;
import com.example.blog.dto.writing.ArticleLikeDto;
import com.example.blog.dto.writing.SupperDto;
import com.example.blog.dto.writing.WritingsDelDto;
import com.example.blog.mapper.WritingsMapper;
import com.example.blog.note.LogInfo;
import com.example.blog.note.NoToken;
import com.example.blog.note.Permissions;

import com.example.blog.service.impl.*;
import com.example.blog.utils.*;
import com.example.blog.vo.writing.WritingRecentlyHotVo;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.*;

@RestController
@Transactional
@Slf4j
@Validated
@RequestMapping("/writings")

public class WritingsController extends BaseController {
    private final WritingsServiceImpl writingsService;
    private final WritingsMapper writingsMapper;
    private final RedisStorage redisStorage;
    private final IdUtils idUtils;

    @Autowired
    public WritingsController(WritingsServiceImpl writingsService,
                              WritingsMapper writingsMapper,
                              RedisStorage redisStorage,
                              IdUtils idUtils) {
        this.writingsService = writingsService;
        this.writingsMapper = writingsMapper;
        this.redisStorage = redisStorage;
        this.idUtils = idUtils;
    }

    // 分页获取首页文章的信息，
    @NoToken
    @LogInfo(value = "分页获取文章")
    @GetMapping("/selectLimit/{index}")
    public Response selectLimit(@Validated @Min(value = 1, message = "最小值为1") @PathVariable("index") Integer index) {
        IPage page = new Page(Long.parseLong(index.toString()), 8);
        LambdaQueryWrapper<Writings> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Writings::getStatus, 1).eq(Writings::getStatus, 1);
        return new Response(Response.SUCCEED_CODE, "分页获取首页文章", writingsService.page(page, wrapper).getRecords());
    }


    //搜索模糊查询
    @NoToken
    @LogInfo("搜索模糊查询")
    @GetMapping("/fuzzyQueries/{searchData}")
    public Response fuzzyQueries(@NotNull(message = "不能为空") @PathVariable String searchData) {
        LambdaQueryWrapper<Writings> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(Writings::getTitle, searchData).eq(Writings::getStatus, 1);
        return new Response(Response.SUCCEED_CODE, "搜索查询文章", writingsService.list(wrapper));
    }


    //查询单篇文章
    @NoToken
    @LogInfo("查询单篇文章")
    @GetMapping("/save/{wid}")
    public Response save(@PathVariable("wid") String wid) {
        LambdaQueryWrapper<Writings> wrapper = new LambdaQueryWrapper<Writings>();
        wrapper.eq(Writings::getWid, wid).eq(Writings::getStatus, 1);
        return new Response(Response.SUCCEED_CODE, "查询单篇文章", writingsService.getOne(wrapper));
    }


    //查询单篇文章根据文章标题
    @NoToken
    @LogInfo("查询单篇文章")
    @GetMapping("/getByTitle/{title}")
    public Response getByTitle(@PathVariable("title") String title) {
        LambdaQueryWrapper<Writings> wrapper = new LambdaQueryWrapper<Writings>();
        wrapper.eq(Writings::getTitle, title).eq(Writings::getStatus, 1);
        return new Response(Response.SUCCEED_CODE, "查询单篇文章", writingsService.getOne(wrapper));
    }


    //查询用户前五的文章
    @NoToken
    @LogInfo("查询用户前五的文章")
    @GetMapping("/saveUserFive/{uid}")
    public Response saveUserFive(@PathVariable("uid") long uid) {
        LambdaQueryWrapper<Writings> wrapper = new LambdaQueryWrapper<>();
        IPage page = new Page(1, 5);
        wrapper.eq(Writings::getUid, uid).eq(Writings::getStatus, 1).orderByDesc(Writings::getDate);
        return new Response(Response.SUCCEED_CODE, "查询用户前五的文章", writingsService.page(page, wrapper).getRecords());
    }


    //猜你喜欢
    @NoToken
    @LogInfo("猜你喜欢")
    @GetMapping("/guessyoulike")
    public Response guessYouLike() {
        IPage page = new Page(0, 8);
        LambdaQueryWrapper<Writings> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(Writings::getLikes,Writings::getTitle,Writings::getUid,Writings::getWid)
                .orderByDesc(Writings::getLikes)
                .eq(Writings::getStatus, 1)
                .eq(Writings::getEncrypt, 0);

        return new Response(Response.SUCCEED_CODE, "猜你喜欢", writingsService.page(page, wrapper).getRecords());
    }

    @NoToken
    @LogInfo("最近热门")
    @GetMapping("/recentlyHot")
    public Response recentlyHot() {
        IPage page = new Page(1, 5);
        LambdaQueryWrapper<Writings> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(Writings::getTitle,Writings::getUid,Writings::getWid)
                .orderByDesc(Writings::getVisit)
                .eq(Writings::getStatus, 1)
                .eq(Writings::getEncrypt, 0);
        return new Response(Response.SUCCEED_CODE, "最近热门", writingsService.page(page, wrapper).getRecords());
    }
    //统计用户的总浏览数
    @NoToken
    @LogInfo(value = "统计浏览数")
    @GetMapping("/browseGetAll/{id}")
    public Response browseGetAll(@PathVariable("id") long id) {
        QueryWrapper<Writings> wrapper = new QueryWrapper<>();
        wrapper.select("sum(visit) as visit").eq("uid", id);
        Map<String, Object> comments = writingsService.getMap(wrapper);
        if (comments == null) {
            return new Response(Response.SUCCEED_CODE, "统计浏览数", 0);
        }
        return new Response(Response.SUCCEED_CODE, "统计浏览数", comments.get("visit"));
    }

    //统计用户的总赞数
    @NoToken
    @LogInfo(value = "统计点赞数")
    @GetMapping("/supportGetAll/{id}")
    public Response supportGetAll(@PathVariable("id") long id) {
        if (id == 0) {
            return new Response(Response.ERROR_CODE, "统计点赞数", "失败");
        }
        QueryWrapper<Writings> wrapper = new QueryWrapper<>();
        wrapper.select("sum(likes) as likes").eq("uid", id);
        Map<String, Object> likes = writingsService.getMap(wrapper);
        if (likes == null) {
            return new Response(Response.ERROR_CODE, "修改失败", 0);
        }
        return new Response(Response.SUCCEED_CODE, "成功", likes.get("likes"));
    }


    //赞增加
    @LogInfo(value = "点赞增减")
    @PostMapping("/supportAdd")
    public Response supportAdd(@RequestBody SupperDto writings) {
        UpdateWrapper<Writings> wrapper = new UpdateWrapper<>();
        if (writings.getType() == 0) {
            wrapper.eq("wid", writings.getWid()).setSql("likes = likes + 1");
        } else {
            wrapper.eq("wid", writings.getWid()).setSql("likes = likes - 1");
        }
        return new Response(Response.SUCCEED_CODE, "修改成功", writingsService.update(null, wrapper));
    }

    //浏览增加
    @LogInfo(value = "浏览增加")
    @NoToken
    @GetMapping("/browseAdd/{wid}")
    public Response browseAdd(@PathVariable("wid") String wid) {
        UpdateWrapper<Writings> wrapper = new UpdateWrapper<>();
        wrapper.eq("wid", wid).setSql("visit = visit + 1");
        return new Response(Response.SUCCEED_CODE, "新增成功", writingsService.update(null, wrapper));
    }


    //文章是否点赞
    @NoToken
    @LogInfo(value = "Redis检查点赞状态")
    @PostMapping("/supportStatue")
    public Response supportStatues(@RequestBody ArticleLikeDto writings) throws JsonProcessingException {
        return new Response(Response.SUCCEED_CODE, "检查成功", (Boolean) redisStorage.supportStatue(writings));
    }


    //文章点赞的增减操作
    @LogInfo(value = "Redis修改点赞状态")
    @PostMapping("/supportChoose")
    public Response supportChoose(@RequestBody ArticleLikeDto writings) throws JsonProcessingException {
        return new Response(Response.SUCCEED_CODE, "Redis修改点赞成功", redisStorage.supportChoose(writings));
    }


    //新增文章
    @LogInfo(value = "新增文章")
    @PostMapping("/writingsAdd")
    public Response writingsAdd(MultipartFile[] files, String writing) {
        Writings writings = JSON.parseObject(writing, Writings.class);
        writings.setWid(idUtils.createUid());
        writings.setUid(getLogSign().getUid());
        return new Response(Response.SUCCEED_CODE, "新增成功", writingsService.newArticle(files, writings));
    }

    //删除文章
    @LogInfo(value = "删除文章")
    @DeleteMapping("/writingsDel/{id}")
    public Response writingsDel(@PathVariable("id") String id) {
        UpdateWrapper<Writings> wrapper = new UpdateWrapper<>();
        wrapper.eq("wid", id).set("status", -1);
        return new Response(
                Response.SUCCEED_CODE,
                "删除文章",
                writingsService.update(null, wrapper));
    }

    //更新文章
    @LogInfo(value = "更新文章信息")
    @PostMapping("/update")
    public Response writingsUpdate(@RequestParam(value = "files", required = false) MultipartFile[] files,
                                   @RequestParam(value = "writings") String writings) {
        Writings writings_ = JSON.parseObject(writings, Writings.class);

        Optional.ofNullable(writingsService.list(new LambdaQueryWrapper<Writings>().eq(Writings::getUid, getLogSign().getUid())))
                .ifPresent(s -> {
                    writingsService.updateArticle(files, writings_);
                });
        return new Response(Response.SUCCEED_CODE, "更新成功", 1);
    }

    //获取用户所有的文章信息
    @NoToken
    @GetMapping("/getUserAll/{uid}")
    @LogInfo(value = "获取用户所有文章")
    public Response getUserAll(@Min(value = 1, message = "最小值为1") @PathVariable("uid") long uid) {
        HttpServletRequest request = getHttpInfo();
        Claims claims = JwtUtils.checkToken(request.getHeader("token"));
        if (!String.valueOf(claims.get("uid")).equals(String.valueOf(uid))) {
            return new Response(Response.ERROR_CODE, "获取用户文章", null);
        }
        LambdaQueryWrapper<Writings> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Writings::getUid, uid)
                .orderByDesc(Writings::getDate)
                .ne(Writings::getStatus, -1);
        return new Response(Response.SUCCEED_CODE, "获取用户文章", writingsService.list(wrapper));
    }

    //Admin删除文章
    @LogInfo(value = "Admin根据文章id删除文章")
    @Permissions("/admin/writingsDel")
    @PostMapping("/admin/writingsDel")
    public Response writingsAdminDel(@RequestBody WritingsDelDto writingsDelDto) {
        OperationLogsDto logsVo = new OperationLogsDto(
                -1, IpUtil.getIpAddress(getHttpInfo()), "Admin根据文章id删除文章", getLogSign(), "文章ID：".concat(StringUtils.join(writingsDelDto.getWid(), ",")));
        return new Response(Response.SUCCEED_CODE, "删除文章", writingsService.delWritingId(writingsDelDto, logsVo));
    }

    //Admin删除用户所有文章
    @LogInfo(value = "Admin删除用户所有文章")
    @NoToken
    @Permissions("/admin/writingsUserDel")
    @DeleteMapping("/admin/writingsUserDel/{id}")
    public Response writingsAdminDelAll( @Min(value = 1, message = "最小值为1") @PathVariable("id") long id) {
        OperationLogsDto logsVo = new OperationLogsDto(
                -1, IpUtil.getIpAddress(getHttpInfo()), "Admin删除用户所有文章", getLogSign(), "文章ID：".concat(String.valueOf(id)));
        return new Response(Response.SUCCEED_CODE, "删除成功", writingsService.writingsAdminDelAll(id, logsVo));
    }


    // 分页获取首页文章的信息(后台管理,按条件)
    @Permissions("/writings/selectLimitAdmin")
    @PostMapping("/selectLimitAdmin")
    @LogInfo(value = "Admin分页获取文章")
    public Response selectLimitInformationAdmin(@RequestBody AdminWritingSelectDto articleInformationPage) {
        Page page = new Page(articleInformationPage.getIndex(), articleInformationPage.getPage());
        LambdaQueryWrapper<Writings> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .orderByDesc(articleInformationPage.getSortBy()==0 ,Writings::getDate)
                .orderByDesc(articleInformationPage.getSortBy()== 1,Writings::getLikes)
                .orderByDesc(articleInformationPage.getSortBy()== 2,Writings::getVisit)
                .eq(articleInformationPage.getTypes() != 2, Writings::getStatus, articleInformationPage.getTypes())
                .like(articleInformationPage.getTitle()!=null,Writings::getTitle,articleInformationPage.getTitle())
                .like(articleInformationPage.getDateTime()!=null,Writings::getDate,articleInformationPage.getDateTime());
        Optional.ofNullable(articleInformationPage.getCondition())
                .ifPresent(s -> {
                    queryWrapper.and(wrapper -> wrapper.like(Writings::getUid, articleInformationPage.getCondition())
                            .or().like(Writings::getWid, articleInformationPage.getCondition())
                            .or().like(articleInformationPage.getCondition().length() > 20, Writings::getBody, articleInformationPage.getCondition()));
                });
        return new Response(Response.SUCCEED_CODE, "获取成功", writingsService.page(page, queryWrapper));
    }

    //更新文章信息(后台管理)
    @Permissions("/writings/updateAdmin")
    @PostMapping("/updateAdmin")
    @LogInfo(value = "Admin更新文章")
    public Response updateAdmin(@RequestBody AdminWritingsUpdateDto writings) {
        OperationLogsDto logsVo = new OperationLogsDto(
                0, IpUtil.getIpAddress(getHttpInfo()), "Admin更新文章", getLogSign(), "文章ID：".concat(writings.getWid()));
        return new Response(Response.SUCCEED_CODE, "更新成功", writingsService.updateAdminWriting(writings,logsVo));
    }

    //搜索(后台管理)
    @Permissions("/writings/searchAdmin")
    @GetMapping("/searchAdmin/{msg}")
    @LogInfo(value = "Admin搜索文章")
    public Response selectAdminSearch(@NotBlank(message = "不能为空") @PathVariable("msg") String msg) {
        LambdaQueryWrapper<Writings> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(Writings::getDate)
                .like(Writings::getWid, msg)
                .or()
                .like(Writings::getTitle, msg)
                .or()
                .like(Writings::getType, msg)
                .or()
                .like(Writings::getUid, msg);
        return new Response(Response.SUCCEED_CODE, "搜索成功", writingsService.list(wrapper));
    }


    //获取文章总数
    @Permissions("/writings/length")
    @GetMapping("/length")
    @LogInfo(value = "Admin获取文章总数")
    public Response writingsNum() {
        return new Response(Response.SUCCEED_CODE, "获取成功", writingsMapper.writingsLength());
    }

    //获取未审核文章
    @Permissions("/writings/writingsState")
    @LogInfo(value = "获取未审核文章")
    @GetMapping("/writingsState")
    public Response writingsState() {
        return new Response(
                Response.SUCCEED_CODE,
                "获取成功",
                writingsService.list(new LambdaQueryWrapper<Writings>().eq(Writings::getStatus, 0)));
    }
}
